using System;
using Synapse.Framework.Notifier;
using Synapse.Framework.Pipe.BusinessObjects;
using Synapse.Framework.Pipe.Filters;
using Synapse.Framework.Pipe.Operations;

namespace Synapse.Framework.Pipe.PipeLines
{
    public class Pipe<TPump,TInput,TX> : IPipe<TPump,TInput,TX>
    {
        private readonly IPipeLine pipeLine;
        private readonly INotifier notifier;

        public Pipe(IPipeLine pipeLine, INotifier notifier)
        {
            this.pipeLine = pipeLine;
            this.notifier = notifier;
        }

        public void Pump(TPump input)
        {
            pipeLine.Execute(new BusinessObjet<TPump>(input));
        }

        public IPipe<TPump, TOutput, TInput> Pin<TOutput>(IOperation<TInput, TOutput> operation)
        {
            return register(operation);
        }

        public IPipe<TPump, TOutput, TInput> Pin<TOutput>(Func<TInput, TOutput> operation)
        {
            return register(new OperationFuncAdapter<TInput, TOutput>(operation));
        }

        public IPipe<TPump, TOutput, TInput> Pin<TOutput>(Func<IPipe<TPump, TInput, TX>, IOperation<TInput, TOutput>> operation)
        {
            return register(operation(this));
        }

        private IPipe<TPump, TOutput, TInput> register<TOutput>(IOperation<TInput, TOutput> operation)
        {
            pipeLine.Add(new FilterAOP<TInput, TOutput>(operation, notifier));
            return new Pipe<TPump, TOutput, TInput>(pipeLine, notifier);
        }
    }
}